﻿using IP2Region.Net.Abstractions;
using Microsoft.AspNetCore.SignalR;
using Microsoft.IdentityModel.Tokens;
using Shyjus.BrowserDetection;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Zhp.Auth.IService;
using Zhp.Auth.Model;
using Zhp.Cache;
using Zhp.Common.Helper;
using Zhp.Common.WebApp;
using Zhp.Entity.SysEnum;
using Zhp.IService.Chat;
using Zhp.IService.Common;
using Zhp.Model.Chat;

namespace Zhp.Api.ChatHub
{
    public class ChatHub : Hub
    {
        private readonly ICacheService _cache;
        private readonly IChatMessageService _chatMessageSvc;
        private readonly ISearcher _ipSearcher;
        private readonly IBrowserDetector _browser;
        private readonly IOnlineService _onlineSvc;
        private readonly IFileService _fileSvc;
        private readonly ICurrentUser _currentUser;
        public ChatHub(ICacheService cache, IChatMessageService chatMessageService, ISearcher searcher, IBrowserDetector browser, IOnlineService onlineSvc, IFileService fileSvc, ICurrentUser currentUser)
        {
            _cache = cache;
            _chatMessageSvc = chatMessageService;
            _ipSearcher = searcher;
            _browser = browser;
            _onlineSvc = onlineSvc;
            _fileSvc = fileSvc;
            _currentUser = currentUser;
        }

        public override Task OnConnectedAsync()
        {
            if (Context.User != null)
            {
                var connectionId = Context.ConnectionId;
                var remoteIp = Context.GetHttpContext()?.Connection.RemoteIpAddress?.ToString() ?? "0.0.0.0";

                if (_currentUser != null)
                {
                    var user = new OnlineUserModel
                    {
                        TokenId = _currentUser.TokenId,
                        UserId = _currentUser.UserId,
                        UserName = _currentUser.Name,
                        NickName = _currentUser.NickName,
                        ConnectionId = connectionId,
                        RequestIp = remoteIp,
                        IpAddress = _ipSearcher.Search(remoteIp),
                        OperatingSystem = _browser.Browser?.OS,
                        DeviceType = _browser.Browser?.DeviceType,
                        BrowserName = _browser.Browser?.Name,
                        Version = _browser.Browser?.Version,
                        LoginTime = DateTime.Now,
                    };
                    if (_onlineSvc.IsMultiClientLogin())
                    {
                        _cache.HashListSet(CacheKey.OnlineActiveUser, (x) => connectionId, user);
                    }
                    else
                    {
                        _cache.HashListSet(CacheKey.OnlineActiveUser, (x) => _currentUser.UserId, user);
                    }
                }
            }

            return base.OnConnectedAsync();
        }

        public override Task OnDisconnectedAsync(Exception exception)
        {
            if (Context.User != null)
            {
                if (_currentUser != null)
                {
                    var connectionId = Context.ConnectionId;
                    if (_onlineSvc.IsMultiClientLogin())
                    {
                        _cache.HashListDelete(CacheKey.OnlineActiveUser, connectionId);
                    }
                    else
                    {
                        _cache.HashListDelete(CacheKey.OnlineActiveUser, _currentUser.UserId.ToString());
                    }
                }
            }

            return base.OnDisconnectedAsync(exception);
        }

        public async Task OnMessage(string message)
        {
            if (Context.User == null)
            {
                return;
            }
            var chat = message.ToObject<ChatMessageModel>();
            chat.SenderId = _currentUser.UserId;
            chat.SenderName = _currentUser.NickName;
            chat.SendTime = DateTime.Now;
            chat.ReceiveTime = DateTime.Now;
            chat.TimeStamp = DateTime.Now.Ticks;
            
            //消息存入数据库
            try
            {
                await _chatMessageSvc.Create(chat);
            }
            catch (Exception e)
            {
                string error = e.Message;
                throw;
            }

            var onlineList = _cache.HashListGetAll<OnlineUserModel>(CacheKey.OnlineActiveUser);
            var toConnectionIdList = onlineList.Where(x => x.UserId == chat.TouserId).Select(x => x.ConnectionId).ToList();
            if (toConnectionIdList.Any())
            {
                if (chat.MessageType == MessageTypeEnum.Img)
                {
                    chat.Content = _fileSvc.GetStreamUrl(Convert.ToInt64(chat.Content));
                }
                await Clients.Clients(toConnectionIdList).SendAsync("OnMessage", chat);
            }
        }
    }
}
